package com.thm.tfast.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.thm.tfast.core.enums.DeleteFlagEnum;
import com.thm.tfast.core.enums.StatusEnum;
import com.thm.tfast.core.exception.Asserts;
import com.thm.tfast.core.sevruity.domain.SysUserDetails;
import com.thm.tfast.core.utils.SecurityUtil;
import com.thm.tfast.modules.sys.mapper.SysRoleMapper;
import com.thm.tfast.modules.sys.model.*;
import com.thm.tfast.modules.sys.model.dto.role.RoleInsertDto;
import com.thm.tfast.modules.sys.model.dto.role.RoleMenuDto;
import com.thm.tfast.modules.sys.model.dto.role.RolePermissionDto;
import com.thm.tfast.modules.sys.model.dto.role.RoleUpdateDto;
import com.thm.tfast.modules.sys.model.vo.role.RoleVo;
import com.thm.tfast.modules.sys.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author THM
 * @since 2022-10-10
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
    @Resource
    private SysCacheService sysCacheService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysRoleMenuService sysRoleMenuService;
    @Resource
    private SysRolePermissionService sysRolePermissionService;
    @Override
    public List<RoleVo> getRolesByUserId(Long userId) {
        List<SysRole> roles = this.baseMapper.getRolesByUserId(userId);
        return BeanUtil.copyToList(roles,RoleVo.class);
    }

    @Override
    public Page<SysRole> page(String keyword, Integer pageNum, Integer pageSize) {
        Page<SysRole> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SysRole> wrapper = Wrappers.lambdaQuery();
        if (StrUtil.isNotEmpty(keyword)) {
            wrapper.like(SysRole::getName, keyword);
        }
        wrapper.ne(SysRole::getDelFlag,DeleteFlagEnum.DELETED.getCode());
        return this.page(page, wrapper);
    }

    @Override
    @Transactional
    public Long insert(RoleInsertDto dto) {
        SysRole sysRole = BeanUtil.toBean(dto, SysRole.class);
        int count = this.count(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getName, sysRole.getName()));
        if (count != 0){
            Asserts.fail("角色名已存在");
        }
        sysRole.setDelFlag(DeleteFlagEnum.UNDELETE.getCode());
        SysUserDetails currentUser = SecurityUtil.getCurrentUser();
        sysRole.setCreateUser(currentUser.getUserId());
        sysRole.setCreateTime(currentUser.getDate());
        sysRole.setUpdateUser(currentUser.getUserId());
        sysRole.setUpdateTime(currentUser.getDate());
        this.save(sysRole);
        return sysRole.getId();
    }

    @Override
    @Transactional
    public boolean update(RoleUpdateDto dto) {
        if (Objects.isNull(this.getById(dto.getId()))){
            Asserts.fail("角色信息不存在");
        }
        SysRole sysRole = BeanUtil.toBean(dto, SysRole.class);
        SysUserDetails currentUser = SecurityUtil.getCurrentUser();
        sysRole.setUpdateUser(currentUser.getUserId());
        sysRole.setUpdateTime(currentUser.getDate());
        //删除与角色相关缓存
        sysCacheService.delRoleByRoleId(dto.getId());
        return this.updateById(sysRole);
    }

    @Override
    @Transactional
    public boolean enableOrDisable(Long roleId) {
        SysRole sysRole = this.getById(roleId);
        if (Objects.isNull(sysRole)){
            Asserts.fail("角色信息不存在");
        }
        Integer status;
        if (Objects.equals(sysRole.getStatus(), StatusEnum.ENABLE.getCode())) {
            //判断是否关联用户
            int count = sysUserRoleService.count(Wrappers
                    .<SysUserRole>lambdaQuery()
                    .eq(SysUserRole::getRoleId, roleId));
            if (count != 0){
                Asserts.fail("角色已绑定用户不能禁用！");
            }
            //禁用
            status = StatusEnum.DISABLE.getCode();
        } else {
            //启用
            status = StatusEnum.ENABLE.getCode();
        }
        SysUserDetails currentUser = SecurityUtil.getCurrentUser();
        sysRole.setStatus(status);
        sysRole.setUpdateUser(currentUser.getUserId());
        sysRole.setUpdateTime(currentUser.getDate());
        return this.updateById(sysRole);
    }

    @Override
    @Transactional
    public boolean delete(Long roleId) {
        SysRole sysRole = this.getById(roleId);
        if (Objects.isNull(sysRole)){
            Asserts.fail("角色信息不存在");
        }
        int count = sysUserRoleService.count(Wrappers
                .<SysUserRole>lambdaQuery()
                .eq(SysUserRole::getRoleId, roleId));
        if (count != 0){
            Asserts.fail("角色已绑定用户不能删除！");
        }
        //逻辑删除角色
        SysUserDetails currentUser = SecurityUtil.getCurrentUser();
        sysRole.setUpdateUser(currentUser.getUserId());
        sysRole.setUpdateTime(currentUser.getDate());
        sysRole.setDelFlag(DeleteFlagEnum.DELETED.getCode());
        return this.updateById(sysRole);
    }

    @Override
    @Transactional
    public boolean allotMenu(RoleMenuDto dto) {
        if (Objects.isNull(this.getById(dto.getRoleId()))){
            Asserts.fail("角色信息不存在");
        }
        //删除角色菜单
        sysRoleMenuService.remove(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId,dto.getRoleId()));
        //删除与角色菜单相关缓存
        sysCacheService.delMenuByRoleId(dto.getRoleId());
        //新增角色菜单
        List<SysRoleMenu> sysRoleMenus = dto.getMenuIds().stream().map(menuId -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(dto.getRoleId());
            sysRoleMenu.setMenuId(menuId);
            return sysRoleMenu;
        }).collect(Collectors.toList());
        return sysRoleMenuService.saveBatch(sysRoleMenus);
    }

    @Override
    @Transactional
    public boolean allotPermission(RolePermissionDto dto) {
        if (Objects.isNull(this.getById(dto.getRoleId()))){
            Asserts.fail("角色信息不存在");
        }
        //删除角色权限
        sysRolePermissionService.remove(Wrappers.<SysRolePermission>lambdaQuery().eq(SysRolePermission::getRoleId,dto.getRoleId()));
        //删除与角色权限相关缓存
        sysCacheService.delPermissionByRoleId(dto.getRoleId());
        //新增角色权限
        List<SysRolePermission> sysRolePermissions = dto.getPermissionIds().stream().map(permissionId -> {
            SysRolePermission sysRolePermission = new SysRolePermission();
            sysRolePermission.setRoleId(dto.getRoleId());
            sysRolePermission.setPermissionId(permissionId);
            return sysRolePermission;
        }).collect(Collectors.toList());
        return sysRolePermissionService.saveBatch(sysRolePermissions);
    }
}
